package com.wang.demo.application.server;

import com.wang.demo.application.handler.*;
import com.wang.demo.protocol.codec.MessageCodec;
import com.wang.demo.protocol.codec.MessageCodecSharable;
import com.wang.demo.protocol.codec.ProcotoFrameDecoder;
import com.wang.demo.service.Session;
import com.wang.demo.service.factory.SessionFactory;
import com.wang.demo.service.pojo.Group;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * @author: Jeffrey
 * @date: 2022/01/21/9:21
 * @description:
 */
@Slf4j
public class ChatServer {

    public static void main(String[] args) {

        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();

        try {
            LoggingHandler LOGGING_HANDLER = new LoggingHandler();
            MessageCodecSharable MESSAGE_CODEC = new MessageCodecSharable();
            LoginHandler LOGIN_HANDLER = new LoginHandler();
            PersonChatHandler PERSON_CHAT_HANDLER = new PersonChatHandler();
            QuitHandler QUIT_HANDLER =new QuitHandler();
            GroupCreateRequestMessageHandler CREATE_GROUP_HANDLER = new GroupCreateRequestMessageHandler();
            GroupChatRequestMessageHandler CHAT_GROUP_HANDLER = new GroupChatRequestMessageHandler();
            GroupJoinRequestMessageHandler JOIN_GROUP_HANDLER = new GroupJoinRequestMessageHandler();
            GroupQuitHandler GROUP_QUIT_HANDLER = new GroupQuitHandler();
            GroupMemberRequestMessageHandler GROUP_MEMBERS_HANDLER =new GroupMemberRequestMessageHandler();

            Channel channel = new ServerBootstrap()
                    .group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) throws Exception {
                             ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new IdleStateHandler(5,0,0))
                                    .addLast(new ChannelDuplexHandler(){
                                        @Override
                                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                                            IdleStateEvent event = (IdleStateEvent) evt;
                                            if (event.state() == IdleState.READER_IDLE){
                                                /*对超时假死用户进行处理*/
                                                SessionFactory.getSession().unbind(ctx.channel());
                                            }
                                            super.userEventTriggered(ctx, evt);
                                        }
                                    })
                                    .addLast(new ProcotoFrameDecoder())
                                    .addLast(LOGGING_HANDLER)
                                    .addLast(MESSAGE_CODEC)
                                    .addLast(LOGIN_HANDLER)
                                    .addLast(PERSON_CHAT_HANDLER)
                                    .addLast(QUIT_HANDLER)
                                    .addLast(CREATE_GROUP_HANDLER)
                                    .addLast(CHAT_GROUP_HANDLER)
                                    .addLast(JOIN_GROUP_HANDLER)
                                    .addLast(GROUP_QUIT_HANDLER)
                                    .addLast(GROUP_MEMBERS_HANDLER);
                        }
                    }).bind("localhost",8080).sync().channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("Server error{}",e.getMessage());
        }finally {
            /*发送完缓存中的数据后关闭资源*/
            worker.shutdownGracefully();
            boss.shutdownGracefully();
        }
    }
}
